﻿



namespace Common.Algorithm.Core;

public class GraphGenerator
{
    public static IList<GraphEdge> GenDirectalWeightGraph()
    {
        List<GraphEdge> edges = new List<GraphEdge>();
        edges.Add(new GraphEdge() { stVertexId = 1, edVertexId = 1, weight = 0 });
        edges.Add(new GraphEdge() { stVertexId = 2, edVertexId = 2, weight = 0 });
        edges.Add(new GraphEdge() { stVertexId = 3, edVertexId = 3, weight = 0 });
        edges.Add(new GraphEdge() { stVertexId = 4, edVertexId = 4, weight = 0 });
        edges.Add(new GraphEdge() { stVertexId = 5, edVertexId = 5, weight = 0 });
        edges.Add(new GraphEdge() { stVertexId = 6, edVertexId = 6, weight = 0 });
        edges.Add(new GraphEdge() { stVertexId = 7, edVertexId = 7, weight = 0 });

        edges.Add(new GraphEdge() { stVertexId = 3, edVertexId = 1, weight = 4 });
        edges.Add(new GraphEdge() { stVertexId = 3, edVertexId = 6, weight = 5 });
        edges.Add(new GraphEdge() { stVertexId = 1, edVertexId = 2, weight = 2 });
        edges.Add(new GraphEdge() { stVertexId = 1, edVertexId = 4, weight = 1 });
        edges.Add(new GraphEdge() { stVertexId = 2, edVertexId = 4, weight = 3 });
        edges.Add(new GraphEdge() { stVertexId = 2, edVertexId = 5, weight = 10 });
        edges.Add(new GraphEdge() { stVertexId = 4, edVertexId = 3, weight = 2 });
        edges.Add(new GraphEdge() { stVertexId = 4, edVertexId = 6, weight = 8 });
        edges.Add(new GraphEdge() { stVertexId = 4, edVertexId = 7, weight = 4 });
        edges.Add(new GraphEdge() { stVertexId = 4, edVertexId = 5, weight = 2 });
        edges.Add(new GraphEdge() { stVertexId = 5, edVertexId = 7, weight = 1 });
        edges.Add(new GraphEdge() { stVertexId = 7, edVertexId = 6, weight = 1 });
        return edges;
    }
    public static IList<GraphEdge> GenUNndirectalWeightGraph()
    {
        List<GraphEdge> edges = new List<GraphEdge>();
        edges.Add(new GraphEdge() { stVertexId = 1, edVertexId = 1, weight = 0 });
        edges.Add(new GraphEdge() { stVertexId = 2, edVertexId = 2, weight = 0 });
        edges.Add(new GraphEdge() { stVertexId = 3, edVertexId = 3, weight = 0 });
        edges.Add(new GraphEdge() { stVertexId = 4, edVertexId = 4, weight = 0 });
        edges.Add(new GraphEdge() { stVertexId = 5, edVertexId = 5, weight = 0 });
        edges.Add(new GraphEdge() { stVertexId = 6, edVertexId = 6, weight = 0 });
        edges.Add(new GraphEdge() { stVertexId = 7, edVertexId = 7, weight = 0 });

        edges.Add(new GraphEdge() { stVertexId = 3, edVertexId = 1, weight = 4 });
        edges.Add(new GraphEdge() { stVertexId = 1, edVertexId = 3, weight = 4 });

        edges.Add(new GraphEdge() { stVertexId = 3, edVertexId = 6, weight = 5 });
        edges.Add(new GraphEdge() { stVertexId = 6, edVertexId = 3, weight = 5 });

        edges.Add(new GraphEdge() { stVertexId = 1, edVertexId = 2, weight = 2 });
        edges.Add(new GraphEdge() { stVertexId = 2, edVertexId = 1, weight = 2 });

        edges.Add(new GraphEdge() { stVertexId = 1, edVertexId = 4, weight = 1 });
        edges.Add(new GraphEdge() { stVertexId = 4, edVertexId = 1, weight = 1 });

        edges.Add(new GraphEdge() { stVertexId = 2, edVertexId = 4, weight = 3 });
        edges.Add(new GraphEdge() { stVertexId = 4, edVertexId = 2, weight = 3 });

        edges.Add(new GraphEdge() { stVertexId = 2, edVertexId = 5, weight = 10 });
        edges.Add(new GraphEdge() { stVertexId = 5, edVertexId = 2, weight = 10 });

        edges.Add(new GraphEdge() { stVertexId = 4, edVertexId = 3, weight = 2 });
        edges.Add(new GraphEdge() { stVertexId = 3, edVertexId = 4, weight = 2 });

        edges.Add(new GraphEdge() { stVertexId = 4, edVertexId = 6, weight = 8 });
        edges.Add(new GraphEdge() { stVertexId = 6, edVertexId = 4, weight = 8 });

        edges.Add(new GraphEdge() { stVertexId = 4, edVertexId = 7, weight = 4 });
        edges.Add(new GraphEdge() { stVertexId = 7, edVertexId = 4, weight = 4 });

        edges.Add(new GraphEdge() { stVertexId = 4, edVertexId = 5, weight = 2 });
        edges.Add(new GraphEdge() { stVertexId = 5, edVertexId = 4, weight = 2 });

        edges.Add(new GraphEdge() { stVertexId = 5, edVertexId = 7, weight = 1 });
        edges.Add(new GraphEdge() { stVertexId = 7, edVertexId = 5, weight = 1 });

        edges.Add(new GraphEdge() { stVertexId = 6, edVertexId = 7, weight = 1 });
        edges.Add(new GraphEdge() { stVertexId = 7, edVertexId = 6, weight = 1 });
        return edges;
    }

    public static IList<GraphEdge> GenGraphFullUDW(int count)
    {
        List<GraphEdge> edges = new List<GraphEdge>();

        for (int i = 0; i < count; i++)
        {
            for (int j = 0; j < count; j++)
            {
                edges.Add(new GraphEdge() { stVertexId = i, edVertexId = j, weight = (i - j + count + 1) * 0.5 });
            }
        }
        return edges;
    }

    public static IList<GraphEdge> GenGraphFullUDW()
    {
        List<GraphEdge> edges = new List<GraphEdge>();
        edges.Add(new GraphEdge() { stVertexId = 0, edVertexId = 0, weight = 0 });
        edges.Add(new GraphEdge() { stVertexId = 1, edVertexId = 1, weight = 0 });
        edges.Add(new GraphEdge() { stVertexId = 2, edVertexId = 2, weight = 0 });
        edges.Add(new GraphEdge() { stVertexId = 3, edVertexId = 3, weight = 5 });

        edges.Add(new GraphEdge() { stVertexId = 0, edVertexId = 1, weight = 5 });
        edges.Add(new GraphEdge() { stVertexId = 1, edVertexId = 0, weight = 5 });

        edges.Add(new GraphEdge() { stVertexId = 0, edVertexId = 2, weight = 5 });
        edges.Add(new GraphEdge() { stVertexId = 2, edVertexId = 0, weight = 5 });

        edges.Add(new GraphEdge() { stVertexId = 0, edVertexId = 2, weight = 5 });
        edges.Add(new GraphEdge() { stVertexId = 2, edVertexId = 0, weight = 5 });

        return edges;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="cityFile"></param>
    /// <param name="dataNum"></param>
    /// <returns></returns>
    public static IList<GraphEdge> GenCityGraph(string cityFile, int dataNum = 70)
    {
        //string cityFile = @"D:\WORKSPACE\CODE_CAD\Ant-Colony-Algorithm\pr76.txt";
        Cities Berlin = new Cities(dataNum, cityFile);

        List<GraphEdge> edgess = new List<GraphEdge>();
        for (int i = 0; i < Berlin.Coordinate.Length; i++)
        {
            for (int j = 0; j < Berlin.Coordinate.Length; j++)
            {
                edgess.Add(new GraphEdge() { stVertexId = i, edVertexId = j, weight = Berlin.GetDistance(i, j) });
            }
        }
        return edgess;
    }

    public static Matrix<double> GenCityMatrix(string cityFile, int dataNum = 70)
    {
        Cities Berlin = new Cities(dataNum, cityFile);
        int num = Berlin.Coordinate.Length;
        var matrix = Matrix<double>.Build.Dense(num, num);
        List<GraphEdge> edgess = new List<GraphEdge>();
        for (int i = 0; i < num; i++)
        {
            for (int j = 0; j < num; j++)
            {
                matrix[i, j] = Berlin.GetDistance(i, j);
            }
        }
        return matrix;
    }


    /// <summary>
    /// 假设存在五类物品，每类物品中又包含四种具体物品
    /// 现要求从这五类物品中分别选择一种物品放入背包中，使得背包内物品的 总价值最大、总体积最小、总质量最小。
    /// (PS:这里将背包的总质量限制去掉)。
    /// 其中P为每个物品的价值，R为每个物品的体积，C为每个物品质量。
    /// </summary>
    /// <returns></returns>
    public static Matrix<double>[] GenBackupMatrix()
    { 
       var matrixBuilder = Matrix<double>.Build;

        double[,] array2dP = {
            { 3.0, 4.0, 9.0, 15.0, 2 },
            { 4.0, 6.0, 8.0, 10.0, 2.5 },
            { 5.0, 7.0, 10.0, 12.0, 3.0},
            { 3.0, 5.0, 10.0, 10.0, 2.0},
           };
        var matrixP = matrixBuilder.DenseOfArray(array2dP);

        double[,] array2dR = {
            { 0.2, 0.3, 0.4, 0.6, 0.1 },
            { 0.25, 0.35, 0.38, 0.45, 0.15 },
            { 0.3, 0.37, 0.5,0.5,0.2},
            { 0.3, 0.32, 0.45, 0.6, 0.2},
           };
        var matrixR = matrixBuilder.DenseOfArray(array2dR);

        double[,] array2dC = {
            { 10, 13,24, 32, 4 },
            { 12, 15, 22, 26, 5.2 },
            { 14, 18, 25, 28, 6.8},
            { 14, 14, 28, 32, 6.8},
           };
        var matrixC = matrixBuilder.DenseOfArray(array2dC);

        Matrix<double>[] matrices = new Matrix<double>[3] { matrixP, matrixR, matrixC };
        return matrices;
    }
}

public class Cities
{
    //массив коррдинат городов
    public Point[] Coordinate;
    public Cities(int N, string Path)
    {
        int i = 0;
        Coordinate = new Point[N];
        using (StreamReader sr = new StreamReader(Path, System.Text.Encoding.Default))
        {
            string line;
            while ((line = sr.ReadLine()) != null && i <= N - 1)
            {
                string[] point = line.Split(" ");
                Coordinate[i].X = (int)double.Parse(point[0]);
                Coordinate[i].Y = (int)double.Parse(point[1]);
                i++;
            }
        }
    }
    public double GetDistance(int stIndex, int edIndex)
    {
        var stPnt = Coordinate[stIndex];
        var edPnt = Coordinate[edIndex];

        double dist = Math.Sqrt(Math.Pow(stPnt.X - edPnt.X, 2) + Math.Pow(stPnt.Y - edPnt.Y, 2));
        return dist;
    }

}
